package by.averianov.discounta.services.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.persistence.metamodel.SingularAttribute;

import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import by.averianov.discounta.dataaccess.CardDao;
import by.averianov.discounta.dataaccess.CardTypeDao;
import by.averianov.discounta.dataaccess.ShopDao;
import by.averianov.discounta.dataaccess.UserAccountDao;
import by.averianov.discounta.dataaccess.UserProfileDao;
import by.averianov.discounta.services.UserService;
import by.averianov.discounta.datamodel.Card;
import by.averianov.discounta.datamodel.CardType;
import by.averianov.discounta.datamodel.Shop;
import by.averianov.discounta.datamodel.UserAccount;
import by.averianov.discounta.datamodel.UserProfile;
import by.averianov.discounta.datamodel.enums.AccessGroup;

@Service
public abstract class UserServiceImpl implements UserService {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
	
	@PostConstruct
	private void init() {
		// this method will be called by Spring after bean instantiation. 
		// Can be used for any initialization process.
		LOGGER.info("Instance of UserService is created. Class is: {}", getClass().getName());
	}

	@Inject
	protected UserAccountDao accountDao;
	@Inject
	protected UserProfileDao profileDao;	
	@Inject
	protected ShopDao shopDao;
	@Inject
	protected CardDao cardDao;
	@Inject
	protected CardTypeDao cardTypeDao;
	
    public Long getCurrentDate() {
    	Long unixTime = System.currentTimeMillis();
		Date date=new Date(unixTime);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dateText = sdf.format(date);
        LOGGER.debug("Current date: " + Long.parseLong(dateText));
        LOGGER.debug("Current date example 2: " + sdf.format(System.currentTimeMillis()));
        return Long.parseLong(dateText);
    }
    
    public String randomString(int size) {
        return RandomStringUtils.randomAlphabetic(size);
    }
	
	@Override
    public void saveOrUpdateUser(UserProfile profile, UserAccount account) {
        if (profile.getId() == null) {
            LOGGER.debug("Save new: {}", profile);
            profile.setUserAccount(account);
    		profileDao.insert(profile);
        } else {
            LOGGER.debug("Update: {}", profile);
            profile.setUserAccount(account);
    		profileDao.update(profile);
        }
    }
		
	@Override
	public UserProfile createUserProfile(Long id, String firstName, String lastName, Long dateCreated, Long phone) {
		final UserProfile userProfile = new UserProfile();
		userProfile.setId(id);
		userProfile.setUserFirstName(firstName);
		userProfile.setUserLastName(lastName);
		userProfile.setUserDateCreated(dateCreated);
		userProfile.setPhoneNumber(phone);
		userProfile.setAccessGroup(AccessGroup.user);
		LOGGER.debug(" Create Profile " + userProfile.getUserFirstName());
		return userProfile;
	}
	
	@Override
	public List<UserAccount> getAllAccountOrderId() {
		return accountDao.getAllAccountOrderId();	
	}
	
	@Override
	public UserAccount getUserAccount(Long id) {
		return accountDao.getById(id);
	}
	
	@Override
	public UserProfile getUserProfile(Long id) {
		return profileDao.getById(id);
	}
	
	@Override
	public Shop getShopById(Long id) {
		return shopDao.getById(id);
	}
	
	@Override
	public Card getCardById(Long id) {
		return cardDao.getById(id);
	}
	
	@Override
	public Shop createShop(Long id, String nameShop) {
		Shop shop = new Shop();
		shop.setId(id);
		shop.setNameShop(nameShop);	
		return shop;
	}
	
	@Override
	public CardType getCardTypeByName(String name) {
		return cardTypeDao.getCardTypeByName(name);
	}
	
	@Override
	public void saveOrUpdateShop(Shop shop) {
		if (shop.getId() == null) {
            LOGGER.debug("Save new: {}", shop);
    		shopDao.insert(shop);
        } else {
            LOGGER.debug("Update: {}", shop);
            shopDao.update(shop);
        }
	}
	
	@Override
	public Long getShopCount() {
		return shopDao.getCount();
	}
	
	@Override
	public Long getUserCount() {
		return profileDao.getCount();
	}
	
	@Override
	public Long getCardCount() {
		return cardDao.getCount();
	}
	
	@Override
	public Card getCardByUser(Long userId) {
		Card card = cardDao.getCardByUser(userId);
		return card;
	}

	@Override
	public Set<Shop> getAllShopsByUser(Long userId) {
		UserAccount userAccount = accountDao.getById(userId);
		LOGGER.info("currentAccount for Shops: {}", userAccount.getId());
		Set<Shop> Shops = userAccount.getShops();
		return Shops;
	}
	
	@Override
	public UserAccount getAccountByEmail(String userEmail) {
		return accountDao.getByEmail(userEmail);
	}
	
	@Override
	public List<UserProfile> getAllUserProfile() {
		return profileDao.getAll();
	}
	
	@Override
	public List<CardType> getAllCardType() {
		return cardTypeDao.getAll();
	}

	@Override
	public List<Shop> getAllShop(SingularAttribute<Shop, ?> attr, boolean ascending, int startRecord, int pageSize) {
		return shopDao.getAllShop(attr, ascending, startRecord, pageSize);
	}

	@Override
	public List<UserProfile> getAllUserProfile(SingularAttribute<UserProfile, ?> attr, boolean ascending, int startRecord, int pageSize) {
		return profileDao.getAllUser(attr, ascending, startRecord, pageSize);
	}
	
	@Override
	public List<Card> getAllCard(SingularAttribute<Card, ?> attr, boolean ascending, int startRecord, int pageSize) {
		return cardDao.getAllCard(attr, ascending, startRecord, pageSize);
	}
	
	@Override
	public List<Card> getAllCardByUser(Long id) {
		return cardDao.getAllCardByUser(id);
	}
	
	@Override
	public List<Card> getAllCardByUser(SingularAttribute<Card, ?> attr, boolean ascending, int startRecord, int pageSize, Long id) {
		return cardDao.getAllCardByUser(attr, ascending, startRecord, pageSize, id);
	}
	
	@Override
	public List<CardType> getAllCardType(SingularAttribute<CardType, ?> attr, boolean ascending, int startRecord, int pageSize) {
		return cardTypeDao.getAllCardType(attr, ascending, startRecord, pageSize);
	}
}
